﻿using PBO.Data;
using PBO.Game.BattleLog;
using PokemonBattle.BattleNetwork;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;

namespace PBO.Game.BattleClass
{
    public class BattleReplay
    {
        private Dictionary<byte, TeamData> _teams;
        private Dictionary<byte, string> _players;
        private int _randomSeed;
        private BattleMode _battleMode;

        private List<BattleRule> _rules;
        private List<List<PlayerMove>> _turns;

        private int _turnCount = -1;
        public BattleReplay(Dictionary<byte, TeamData> teamValue, int seedValue, Dictionary<byte, string> playerName, BattleMode mode, List<BattleRule> rules)
        {
            _teams = teamValue;
            _randomSeed = seedValue;
            _players = playerName;
            _battleMode = mode;
            _rules = rules;

            _turns = new List<List<PlayerMove>>();
        }

        public void AddMove(IEnumerable<PlayerMove> moves)
        {
            _turns.Add(moves.ToList());
        }

        public void SaveReplay()
        {
            if (_turns.Count == 0)
                return;
            string savePath = "";
            //if (Properties.Settings.Default.AutoSaveReplay || MessageBox.Show("是否保存战斗录象?", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Information) == DialogResult.Yes)
            //{
            //    if (!string.IsNullOrWhiteSpace(Properties.Settings.Default.RepPath))
            //    {
            //        string name = FileHelper.GetFileName(_players.Values.ToArray());
            //        savePath = Path.Combine(Properties.Settings.Default.RepPath, name + ".pbr");
            //    }
            //    else
            //    {
            //        const string Filter = "战斗录象(*.pbr)|*.pbr";
            //        savePath = FileHelper.SaveFilePath(Filter);
            //    }
            //}
            if (!string.IsNullOrEmpty(savePath))
            {
                FileStream stream = new FileStream(savePath, FileMode.Create);
                BinaryFormatter formatter = new BinaryFormatter();

                BinaryWriter writer = new BinaryWriter(stream);

                try
                {
                    writer.Write((int)_battleMode);
                    writer.Write(_randomSeed);

                    formatter.Serialize(stream, _players);
                    formatter.Serialize(stream, _rules);

                    writer.Write(_teams.Count);
                    foreach (KeyValuePair<byte, TeamData> pair in _teams)
                    {
                        writer.Write(pair.Key);
                        pair.Value.Save(stream);
                    }

                    writer.Write(_turns.Count);
                    foreach (List<PlayerMove> moves in _turns)
                    {
                        writer.Write(moves.Count);
                        foreach (PlayerMove move in moves)
                        {
                            writer.Write((int)move.Pokemon);
                            writer.Write((int)move.Move);
                            writer.Write(move.MoveIndex);
                            writer.Write((int)move.Target);
                        }
                    }
                }
                catch (Exception ex)
                {
                    //MessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                finally
                {
                    writer.Close();
                    stream.Close();
                }
            }
        }

        public static BattleReplay FromFile(string path)
        {
            BattleReplay replay = null;

            FileStream filename = new FileStream(path, FileMode.Open);
            try
            {
                BinaryReader reader = new BinaryReader(filename);

                BinaryFormatter formatter = new BinaryFormatter();

                BattleMode mode = (BattleMode)reader.ReadInt32();
                int seed = reader.ReadInt32();

                Dictionary<byte, string> players = (Dictionary<byte, string>)formatter.Deserialize(filename);
                List<BattleRule> rules = (List<BattleRule>)formatter.Deserialize(filename);

                Dictionary<byte, TeamData> teams = new Dictionary<byte, TeamData>();
                int teamCount = reader.ReadInt32();
                for (int i = 1; i <= teamCount; i++)
                {
                    byte key = reader.ReadByte();
                    TeamData team;// = DataStreamHelper.FromStream<TeamData>(filename);
                    team = new TeamData();
                    team.Load(filename);
                    teams.Add(key, team);
                }

                List<List<PlayerMove>> turns = new List<List<PlayerMove>>();
                int turnCount = reader.ReadInt32();
                for (int i = 1; i <= turnCount; i++)
                {
                    List<PlayerMove> moves = new List<PlayerMove>();
                    int moveCount = reader.ReadInt32();
                    for (int j = 1; j <= moveCount; j++)
                    {
                        PlayerMove move = new PlayerMove();
                        move.Pokemon = (PokemonIndex)reader.ReadInt32();
                        move.Move = (BattleMove)reader.ReadInt32();
                        move.MoveIndex = reader.ReadByte();
                        move.Target = (TargetIndex)reader.ReadInt32();
                        moves.Add(move);
                    }
                    turns.Add(moves);
                }

                replay = new BattleReplay(teams, seed, players, mode, rules);
                replay._turns = turns;
                return replay;
            }
            catch (Exception ex)
            {
                //MessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                filename.Close();
            }
            return null;
        }

        public Battle StartReplay(BattleLogger txt)
        {
            Battle newBattle = new Battle(txt, _battleMode);
            foreach (byte key in _players.Keys)
            {
                newBattle.SetPlayer(key, _players[key]);
            }
            newBattle.SetTeams(_teams);
            newBattle.Rules = _rules;
            newBattle.RandomSeed = _randomSeed;
            newBattle.InitializeBattle();
            Reset();
            return newBattle;
        }

        public List<PlayerMove> NextTurn()
        {
            _turnCount += 1;
            if (_turnCount != _turns.Count)
            {
                return _turns[_turnCount];
            }
            return null;
        }

        public void Reset()
        {
            _turnCount = -1;
        }
    }
}
